﻿using HECore.ServiceFrame.Models;
using HECore.ServiceFrame.Redis;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.OpenApi.Models;
using Refit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace HECore.ServiceFrame.Extensions
{
    /// <summary>
    /// 框架扩展：ServiceCollection
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 框架扩展：注册使用RefitClient
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="services"></param>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public static IServiceCollection FrameRegisterRefitClient<T>(this IServiceCollection services, string serviceName) where T : class
        {
            var configuration = (IConfiguration)services.BuildServiceProvider().GetService(typeof(IConfiguration));

            string BaseAddress = configuration["FrameConfig:Fabio:BaseAddress"];
            services.AddRefitClient<T>().ConfigureHttpClient(c =>
             {
                 c.BaseAddress = new Uri(BaseAddress + "/" + serviceName);

                 var httpContextAccessor = (IHttpContextAccessor)services.BuildServiceProvider().GetService(typeof(IHttpContextAccessor));
                 var httpContextRequestHeaders = httpContextAccessor.HttpContext.Request.Headers;
                 if (httpContextRequestHeaders.ContainsKey("token"))
                 {
                     c.DefaultRequestHeaders.Add("token", httpContextRequestHeaders["token"].ToString());
                 }
             });
            return services;
        }

        /// <summary>
        /// 框架扩展：注册使用服务
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection FrameRegisterService(this IServiceCollection services)
        {
            var AssemblyFiles = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Where(x => x.Contains(".Service.dll"));
            foreach (var AssemblyFile in AssemblyFiles)
            {
                Type[] types = Assembly.LoadFile(AssemblyFile).GetTypes();
                foreach (var t in types)
                {
                    var interfaceTypes = t.GetInterfaces();
                    foreach (var interfaceType in interfaceTypes)
                    {
                        services.TryAddScoped(interfaceType, t);
                    }
                }
            }
            return services;
        }

        /// <summary>
        /// 框架扩展：注册使用Swagger
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection FrameRegisterSwaggerGen(this IServiceCollection services)
        {
            var configuration = (IConfiguration)services.BuildServiceProvider().GetService(typeof(IConfiguration));

            bool IsEnable = bool.Parse(configuration["FrameConfig:Swagger:IsEnable"]);
            if (IsEnable)
            {
                string Title = Assembly.GetCallingAssembly().FullName.Split(',')[0];
                string Description = configuration["FrameConfig:Swagger:Description"];
                services.AddSwaggerGen(option =>
                {
                    option.SwaggerDoc("v1", new OpenApiInfo
                    {
                        Version = "v1",
                        Title = Title,
                        Description = $"{Title}<br/>{Description}"
                    });

                    OpenApiSecurityScheme scheme = new OpenApiSecurityScheme()
                    {
                        Description = "请输入token",
                        Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "token" },
                        Scheme = "oauth2",
                        Name = "token",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey,
                    };
                    option.AddSecurityDefinition("token", scheme);
                    OpenApiSecurityRequirement requirement = new OpenApiSecurityRequirement();
                    requirement[scheme] = new List<string>();
                    option.AddSecurityRequirement(requirement);

                    var XMLFiles = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory).Where(x => x.Contains(".xml"));
                    foreach (var XMLFile in XMLFiles)
                    {
                        option.IncludeXmlComments(XMLFile, true);
                    }
                });
            }
            return services;
        }

        /// <summary>
        /// 框架扩展：注册使用当前员工
        /// 依赖：FrameRegisterRedisClient
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection FrameRegisterCurrentEmployee(this IServiceCollection services)
        {
            services.AddScoped<CurrentEmployee>();
            return services;
        }

        /// <summary>
        /// 框架扩展：注册使用Redis Client
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection FrameRegisterRedisClient(this IServiceCollection services)
        {
            var configuration = (IConfiguration)services.BuildServiceProvider().GetService(typeof(IConfiguration));
            var RedisIP = configuration["FrameConfig:Redis:IP"];
            int RedisPort = int.Parse(configuration["FrameConfig:Redis:Port"]);
            int RedisDefaultDB = int.Parse(configuration["FrameConfig:Redis:DefaultDB"]);
            var RedisPassword = configuration["FrameConfig:Redis:Password"];
            services.AddSingleton(x => new FrameRedisClient(RedisIP, RedisPort, RedisPassword, RedisDefaultDB));
            return services;
        }
    }
}
